/*
 * ebc_proto.c - EBC - protocol handling
 * Clunix, KyungWoon Cho, cezanne@clunix.com, 2006.1
 *
 * Copyright (c) 2001-2008 by Clunix Inc. All Rights Reserved.
 */

#include "config.h"

#include "ebc_p.h"

ebc_msgid_t
ebc_get_msgid(ebc_mch_t *mch)
{
	ebc_msgid_t	msgid;

	ecm_mutex_lock(mch->msgid_lock);
	if (++mch->msgid == EBC_MSGID_NONE)
		mch->msgid++;
	msgid = mch->msgid;
	ecm_mutex_unlock(mch->msgid_lock);
	return msgid;
}

static int
ebc_addr_decode(ebc_addr_t *addr, char *buf)
{
	char	*ptr = buf;
	addr->ndid = ecm_ntohl(*(ebc_ndid_t *)ptr);
	ptr += sizeof(ebc_ndid_t);
	addr->mdid = ecm_ntohl(*(ebc_mdid_t *)ptr);
	ptr += sizeof(ebc_mdid_t);
	addr->ptid = ecm_ntohl(*(ebc_ptid_t *)ptr);
	ptr += sizeof(ebc_ptid_t);
	return (int)(ptr - buf);
}

static int
ebc_addr_encode(ebc_addr_t *addr, char *buf)
{
	char	*ptr = buf;
	*(ebc_ndid_t *)ptr = ecm_htonl(addr->ndid);
	ptr += sizeof(ebc_ndid_t);
	*(ebc_mdid_t *)ptr = ecm_htonl(addr->mdid);
	ptr += sizeof(ebc_mdid_t);
	*(ebc_ptid_t *)ptr = ecm_htonl(addr->ptid);
	ptr += sizeof(ebc_ptid_t);
	return (int)(ptr - buf);
}

void
ebc_pkthdr_decode(ebc_pktb_t *pktb)
{
	ebc_pkthdr_t	*pkth = &pktb->pkthdr;
	char		*ptr = pktb->pktd->data;

	pkth->pver = ecm_ntohs(*((ecm_uint16 *)ptr));
	ptr += sizeof(ecm_uint16);
	pkth->clid = ecm_ntohl(*((ecm_uint32 *)ptr));
	ptr += sizeof(ecm_uint32);
	pkth->pktlen = ecm_ntohs(*((ecm_uint16 *)ptr));
	ptr += sizeof(ecm_uint16);
	ptr += ebc_addr_decode(&pkth->mhdr.srcaddr, ptr);
	ptr += ebc_addr_decode(&pkth->mhdr.dstaddr, ptr);
	pkth->mhdr.msgt = ecm_ntohs(*((ecm_uint16 *)ptr));
	ptr += sizeof(ecm_uint16);
	pkth->mhdr.msgid = ecm_ntohs(*((ebc_msgid_t *)ptr));
	ptr += sizeof(ecm_uint16);
	pkth->pktcnt = ecm_ntohl(*((ecm_uint32 *)ptr));
	ptr += sizeof(ecm_uint32);
	pkth->pktnum = ecm_ntohl(*((ecm_uint32 *)ptr));
}

void
ebc_pkthdr_encode(ebc_pktb_t *pktb)
{
	ebc_pkthdr_t	*pkth = &pktb->pkthdr;
	char	*ptr = pktb->pktd->data;

	*((ecm_uint16 *)ptr) = ecm_htons(pkth->pver);
	ptr += sizeof(ecm_uint16);
	*((ecm_uint32 *)ptr) = ecm_htonl(pkth->clid);
	ptr += sizeof(ecm_uint32);
	*((ecm_uint16 *)ptr) = ecm_htons(pkth->pktlen);
	ptr += sizeof(ecm_uint16);
	ptr += ebc_addr_encode(&pkth->mhdr.srcaddr, ptr);
	ptr += ebc_addr_encode(&pkth->mhdr.dstaddr, ptr);
	*((ecm_uint16 *)ptr) = ecm_htons(pkth->mhdr.msgt);
	ptr += sizeof(ecm_uint16);
	*((ebc_msgid_t *)ptr) = ecm_htons(pkth->mhdr.msgid);
	ptr += sizeof(ecm_uint16);
	*((ecm_uint32 *)ptr) = ecm_htonl(pkth->pktcnt);
	ptr += sizeof(ecm_uint32);
	*((ecm_uint32 *)ptr) = ecm_htonl(pkth->pktnum);
}

ECMBOOL
ebc_mhdr_equal(ebc_mhdr_t *mhdr1, ebc_mhdr_t *mhdr2)
{
	if (ebc_addr_equal(&mhdr1->srcaddr, &mhdr2->srcaddr) &&
	    ebc_addr_equal(&mhdr1->srcaddr, &mhdr2->srcaddr) &&
	    mhdr1->msgt == mhdr2->msgt &&
	    mhdr1->msgid == mhdr2->msgid)
		return ECM_TRUE;
	return ECM_FALSE;
}
